package org.example;

import org.apache.flink.api.common.JobExecutionResult;
import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSink;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.PrintSinkFunction;
import org.apache.flink.streaming.api.functions.sink.SinkFunction;
import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.apache.flink.training.exercises.common.datatypes.EnrichedRide;
import org.apache.flink.training.exercises.common.datatypes.TaxiRide;
import org.apache.flink.training.exercises.common.source.TaxiRideSourceGenerator;
import org.apache.flink.training.exercises.common.utils.GeoUtils;
import org.example.MapFunction.NYCEnrichment;

/**
 * @Author hujf
 * @Date 2022/8/24 11:31
 * @Description TODO
 */
public class RideCleansingExercise {

    private final SourceFunction<TaxiRide> source;
    private final SinkFunction<TaxiRide> sink;

    private final SinkFunction<EnrichedRide> sink2 = new PrintSinkFunction<>();

    public RideCleansingExercise(SourceFunction<TaxiRide> source,SinkFunction<TaxiRide> sink) {
        this.source = source;
        this.sink = sink;
    }

    public static void main(String[] args) throws Exception {
        RideCleansingExercise exercise = new RideCleansingExercise(new TaxiRideSourceGenerator(),new PrintSinkFunction<>());
        exercise.execute();
    }


    public JobExecutionResult execute() throws Exception {

        // set up streaming execution environment
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // set up the pipeline
        DataStreamSource<TaxiRide> taxiRideDataStreamSource = env.addSource(source);

//        taxiRideDataStreamSource.filter(new NYCFilter())
//                .map(new Enrichment())
//                .addSink(sink2);

        taxiRideDataStreamSource.flatMap(new NYCEnrichment())
                .keyBy(o->o.startCell)
                .addSink(sink2);


        // run the pipeline and return the result
        return env.execute("Taxi Ride Cleansing");
    }

    public static class NYCFilter implements FilterFunction<TaxiRide> {
        @Override
        public boolean filter(TaxiRide taxiRide) throws Exception {
            return GeoUtils.isInNYC(taxiRide.startLon, taxiRide.startLat)
                    && GeoUtils.isInNYC(taxiRide.endLon, taxiRide.endLat);
        }
    }
}
